﻿using _01_Tower4._0.CharacterBase.EnemyType;
using _01_Tower4._0.GameFrame;
using _01_Tower4._0.GameFrame.Manager;
using _01_Tower4._0.GameFrame.System;
using _01_Tower4._0.Scene;
using _01_Tower4._0.Tool;
using static _01_Tower4._0.Map;
namespace _01_Tower4._0.CharacterBase
{
    class Hero : Character
    {
        enum State
        {
            None, Up, Down, Left, Right, Enter
        }
        Direction dir;
        Action<Pos> interactionAction;
        State state;
        SceneMap1 scene;
        CombatSystem cs;

        Map map;
        int damage;
        Random rand;
        MaO mao;

        InventorySystem inventory;
        SkillSystem skill;
        DialogSystem ds;

        public static bool canUseKey;
        public static bool canUseKey0;
        public static bool canUseKey1;
        public static bool doorIsOpen1;
        public static bool doorIsOpen2;
        public static int unLock;
        bool trapIsOpen;
        bool trapClear;
        int trapY;
        int trapClearY;
        


        public void AddDef()
        {
            Def++;
        }
        public void AddHp()
        {
            Hp += 2;
        }

        public void AddAtk()
        {
            Atk++;
        }



        public Hero(string name, int hp, int maxHp, int mp, int maxMp, int atk, int def, Pos pos, Map map, string display,ConsoleColor color, SceneMap1 scene,MaO mao) 
            : base(name, hp, maxHp, mp, maxMp, atk, def, pos, map, display,color)
        {
            this.mao = mao;

            this.map = map;
            this.scene = scene;
            inventory = new InventorySystem(60, 14, 16, 12,this);
            skill = new SkillSystem(60, 14, 18, 12, this);
            
        }

        public void Init(Map map, CombatSystem cs, DialogSystem ds)
        {
            this.ds = ds;
            this.cs = cs;
            rand = new Random();
            canUseKey = false;
            canUseKey0 = false;
            canUseKey1 = false;
            doorIsOpen1 = false;
            doorIsOpen2 = false;
            trapIsOpen = false;
            trapY = 1;
            trapClearY = 1;
            unLock = 0;
            inventory.Init();
            skill.Init();

            EventSystem.Instance.AddEvent("魔王战", () =>
            {
                SceneMap1.csTarget = "魔王";
                Console.SetWindowSize(100, 32);
                Console.SetBufferSize(120, 60);
                cs.StartCombat(this, mao, skill);
                skill.Target(mao);
            });
        }
        public override void Render()
        {
            if (SceneManager.sceneName == "SceneMap1")
            {
                switch (dir)
                {
                    case Direction.Up:
                        display = "A";
                        break;
                    case Direction.Down:
                        display = "V";
                        break;
                    case Direction.Left:
                        display = "<";
                        break;
                    case Direction.Right:
                        display = ">";
                        break;
                }
                base.Render();
            }
            if (SceneManager.sceneName == "SceneBag")// 背包
            {
                inventory.Render();
                cs.PlayerInfoRender(this);
            }
            if (SceneManager.sceneName == "SceneSkill")// 技能
            {
                skill.Render();
                cs.PlayerInfoRender(this);
            }
        }
        void Move(Direction dir)
        {
            if (!CanMove(dir))
            {
                return;
            }
            if (map.GetType(Pos) != Map.Type.Tool &&
                map.GetType(Pos) != Map.Type.BluePotion &&
                map.GetType(Pos) != Map.Type.SlimeFall &&
                map.GetType(Pos) != Map.Type.GoblinFall &&
                map.GetType(Pos) != Map.Type.SkillArcane &&
                map.GetType(Pos) != Map.Type.SkillHealing &&
                map.GetType(Pos) != Map.Type.Map2Button0 &&
                map.GetType(Pos) != Map.Type.Map1Key0 &&
                map.GetType(Pos) != Map.Type.Map2Key0 &&
                map.GetType(Pos) != Map.Type.Map2Key1 &&
                map.GetType(Pos) != Map.Type.Map1Step0 &&
                map.GetType(Pos) != Map.Type.Map2Step0 &&
                map.GetType(Pos) != Map.Type.Map2Step1 &&
                map.GetType(Pos) != Map.Type.Map3Step0 &&
                map.GetType(Pos) != Map.Type.TrapWall)
                map.SetType(Pos, Map.Type.None);
            Pos temp = Pos;
            Utility.MyPrint(" ", Pos.x + map.offsetX, Pos.y + map.offsetY);
            switch (dir)
            {
                case Direction.Up:
                    temp.y--;
                    break;
                case Direction.Down:
                    temp.y++;
                    break;
                case Direction.Left:
                    temp.x--;
                    break;
                case Direction.Right:
                    temp.x++;
                    break;
            }
            Pos = temp;
            if (map.GetType(Pos) != Map.Type.Tool &&
                map.GetType(Pos) != Map.Type.BluePotion &&
                map.GetType(Pos) != Map.Type.SlimeFall &&
                map.GetType(Pos) != Map.Type.GoblinFall &&
                map.GetType(Pos) != Map.Type.SkillArcane &&
                map.GetType(Pos) != Map.Type.SkillHealing &&
                map.GetType(Pos) != Map.Type.Map2Button0 &&
                map.GetType(Pos) != Map.Type.Map1Key0 &&
                map.GetType(Pos) != Map.Type.Map2Key0 &&
                map.GetType(Pos) != Map.Type.Map2Key1 &&
                map.GetType(Pos) != Map.Type.Map1Step0 &&
                map.GetType(Pos) != Map.Type.Map2Step0 &&
                map.GetType(Pos) != Map.Type.Map2Step1 &&
                map.GetType(Pos) != Map.Type.Map3Step0 &&
                map.GetType(Pos) != Map.Type.TrapWall)
                map.SetType(Pos, Map.Type.Hero);
            CheckEnemy();
            Pick(Pos);
            
        }

        bool CanMove(Direction dir)
        {
            return map.GetType(GetNextPos(dir)) != Map.Type.Wall
                && map.GetType(GetNextPos(dir)) != Map.Type.FKing
                && map.GetType(GetNextPos(dir)) != Map.Type.MaO
                && map.GetType(GetNextPos(dir)) != Map.Type.RKing
                && map.GetType(GetNextPos(dir)) != Map.Type.NpcPastor
                && map.GetType(GetNextPos(dir)) != Map.Type.BrushMagenta
                && map.GetType(GetNextPos(dir)) != Map.Type.Npc1
                && map.GetType(GetNextPos(dir)) != Map.Type.Npc2;
        }

        public void Pick(Pos pos)
        {
            if(map.GetType(pos) == Map.Type.Tool)
            {
                InfoSystem.Instance.AddInfo("获得生命水晶", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("生命水晶");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.BluePotion)
            {
                InfoSystem.Instance.AddInfo("获得蓝药", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("蓝药");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.SlimeFall)
            {
                InfoSystem.Instance.AddInfo("获得史莱姆凝胶", ConsoleColor.Blue);
                EventSystem.Instance.InvokeEvent("史莱姆凝胶");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.GoblinFall)
            {
                InfoSystem.Instance.AddInfo("获得哥布林长矛", ConsoleColor.Blue);
                EventSystem.Instance.InvokeEvent("哥布林长矛");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.TrapWall)
            {
                EventSystem.Instance.InvokeEvent("玩家死亡");
                SceneManager.Instance.ChangeSceneByName("SceneMenu");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.Map2Button0)
            {
                trapIsOpen = !trapIsOpen;
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.Map2Button0)
            {
                trapIsOpen = !trapIsOpen;
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }

            if (map.GetType(pos) == Map.Type.SkillArcane)
            {
                InfoSystem.Instance.AddInfo("*获得技能书<奥术飞弹>*", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("奥术飞弹");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.SkillHealing)
            {
                InfoSystem.Instance.AddInfo("*获得技能书<治疗魔法>*", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("治疗魔法");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }

            #region Key
            if (map.GetType(pos) == Map.Type.Map1Key0)
            {
                InfoSystem.Instance.AddInfo("获得钥匙1.0", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("钥匙1.0");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.Map2Key0)
            {
                InfoSystem.Instance.AddInfo("获得钥匙2.0", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("钥匙2.0");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            if (map.GetType(pos) == Map.Type.Map2Key1)
            {
                InfoSystem.Instance.AddInfo("获得钥匙2.1", ConsoleColor.Yellow);
                EventSystem.Instance.InvokeEvent("钥匙2.1");
                map.SetType(pos, Map.Type.None);
                Utility.MyPrint("  ", pos.x, pos.y);
            }
            #endregion

            #region Step
            if (map.GetType(pos) == Map.Type.Map1Step0)// 一楼去二楼
            {
                canUseKey = true;
                if (doorIsOpen1)
                {
                    map.ChangeMap(1);
                }
            }
            if (map.GetType(pos) == Map.Type.Map2Step0)// 二楼去一楼
            {
                if (SceneMap1.isBoss)
                {
                    map.ChangeMap(3);
                }
                else
                {
                    map.ChangeMap(0);
                }
            }
            if (map.GetType(pos) == Map.Type.Map2Step1)// 二楼去三楼
            {
                canUseKey0 = true;
                canUseKey1 = true;
                if (doorIsOpen2)
                {
                    map.ChangeMap(2);
                }
            }
            if (map.GetType(pos) == Map.Type.Map3Step0)// 三楼去二楼
            {
                map.ChangeMap(1);
            }
            #endregion
        }

        public void Input()
        {
            if (SceneManager.sceneName == "SceneBag")
            {
                inventory.Input();
            }
            if (SceneManager.sceneName == "SceneSkill")
            {
                skill.Input();
            }
            if (SceneManager.sceneName == "SceneMap1")
            {
                state = State.None;
                if (IsDialoging || IsCombating) return;

                if (InputSystem.Instance.IsKeyPressed(ConsoleKey.W) || InputSystem.Instance.IsKeyPressed(ConsoleKey.UpArrow))
                {
                    state = State.Up;
                }
                if (InputSystem.Instance.IsKeyPressed(ConsoleKey.S) || InputSystem.Instance.IsKeyPressed(ConsoleKey.DownArrow))
                {
                    state = State.Down;
                }
                if (InputSystem.Instance.IsKeyPressed(ConsoleKey.A) || InputSystem.Instance.IsKeyPressed(ConsoleKey.LeftArrow))
                {
                    state = State.Left;
                }
                if (InputSystem.Instance.IsKeyPressed(ConsoleKey.D) || InputSystem.Instance.IsKeyPressed(ConsoleKey.RightArrow))
                {
                    state = State.Right;
                }
                if (InputSystem.Instance.IsKeyPressed(ConsoleKey.Enter))
                {
                    state = State.Enter;
                }
            }
        }
        void ChangeDir(Direction dir)
        {

            this.dir = dir;
        }

        Pos GetNextPos(Direction dir)
        {
            Pos next = Pos;
            switch (dir)
            {
                case Direction.Up:
                    next.y--;
                    break;
                case Direction.Down:
                    next.y++;
                    break;
                case Direction.Left:
                    next.x--;
                    break;
                case Direction.Right:
                    next.x++;
                    break;
            }
            return next;
        }

        void Interaction()
        {
            interactionAction.Invoke(GetNextPos(dir));
        }

        public void AddInteractionAction(Action<Pos> action)
        {
            interactionAction += action;
        }

        public void FixUpdate()
        {
            TrapWallPrint();
            inventory.Update();
            skill.Update();
        }

        void TrapWallPrint()
        {

            if (trapY < 29 && trapIsOpen)
            {
                map.data[map.currentIndex, trapY * 60 + 58].type = Map.Type.TrapWall;
                map.data[map.currentIndex, trapY * 60 + 57].type = Map.Type.TrapWall;
                map.data[map.currentIndex, trapY * 60 + 56].type = Map.Type.TrapWall;
                map.data[map.currentIndex, trapY * 60 + 55].type = Map.Type.TrapWall;
                map.data[map.currentIndex, trapY * 60 + 54].type = Map.Type.TrapWall;
                map.data[map.currentIndex, trapY * 60 + 53].type = Map.Type.TrapWall;
                trapY++;
                trapClear = true;
            }
            else if (trapClearY < 29 && !trapIsOpen && trapClear)
            {
                map.data[map.currentIndex, trapClearY * 60 + 58].type = Map.Type.None;
                map.data[map.currentIndex, trapClearY * 60 + 57].type = Map.Type.None;
                map.data[map.currentIndex, trapClearY * 60 + 56].type = Map.Type.None;
                map.data[map.currentIndex, trapClearY * 60 + 55].type = Map.Type.None;
                map.data[map.currentIndex, trapClearY * 60 + 54].type = Map.Type.None;
                map.data[map.currentIndex, trapClearY * 60 + 53].type = Map.Type.None;
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 58].pos.x, map.data[map.currentIndex, trapClearY * 60 + 58].pos.y);
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 57].pos.x, map.data[map.currentIndex, trapClearY * 60 + 57].pos.y);
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 56].pos.x, map.data[map.currentIndex, trapClearY * 60 + 56].pos.y);
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 55].pos.x, map.data[map.currentIndex, trapClearY * 60 + 55].pos.y);
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 54].pos.x, map.data[map.currentIndex, trapClearY * 60 + 54].pos.y);
                Utility.MyPrint(" ", map.data[map.currentIndex, trapClearY * 60 + 53].pos.x, map.data[map.currentIndex, trapClearY * 60 + 53].pos.y);
                trapClearY++;
            }
        }
        public void Update()
        {
            switch (state)
            {
                case State.Up:
                    Move(Direction.Up);
                    ChangeDir(Direction.Up);
                    break;
                case State.Down:
                    Move(Direction.Down);
                    ChangeDir(Direction.Down);
                    break;
                case State.Left:
                    Move(Direction.Left);
                    ChangeDir(Direction.Left);
                    break;
                case State.Right:
                    Move(Direction.Right);
                    ChangeDir(Direction.Right);
                    break;
                case State.Enter:
                    Interaction();
                    break;
            }
        }

        void CheckEnemy()
        {
            Enemy s = (Enemy)scene.GetGameObject(scene.slime, Pos);
            if (s != null)
            {
                InfoSystem.Instance.AddInfo($"{Name}与{s.Name}遭遇了！");
                SceneMap1.csTarget = "史莱姆";
                cs.StartCombat(this, s, skill);
                skill.Target(s);
            }
            Enemy g = (Enemy)scene.GetGameObject(scene.goblin, Pos);
            if (g != null)
            {
                InfoSystem.Instance.AddInfo($"{Name}与{g.Name}遭遇了！");
                SceneMap1.csTarget = "哥布林";
                cs.StartCombat(this, g, skill);
                skill.Target(g);
            }
        }

        public void End()
        {

        }

        public void SetPos(Pos pos)
        {
            Pos = pos;
        }
    }
}
